/*=============================================================================*
 *  Copyright 2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *=============================================================================*/
package topics.expression.impl;

import org.apache.commons.lang.StringUtils;
import topics.TopicSpace;
import topics.TopicSpaceSet;
import topics.expression.InvalidTopicExpressionException;
import topics.expression.TopicExpression;
import topics.expression.TopicExpressionEvaluator;
import topics.expression.TopicExpressionException;
import topics.expression.TopicExpressionResolutionException;
import util.xml.NamespaceContext;
import javax.xml.namespace.QName;

/**
 * An abstract class that provides functionality that is shared by the
 * {@link TopicExpressionEvaluator}s for all three WS-Topics topic expression
 * dialects.
 *
 * @author Ian Springer (ian DOT springer AT hp DOT com)
 */
public abstract class AbstractTopicExpressionEvaluator
   implements TopicExpressionEvaluator
{
   /**
    * DOCUMENT_ME
    *
    * @param topicExpr DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws TopicExpressionException DOCUMENT_ME
    * @throws InvalidTopicExpressionException DOCUMENT_ME
    */
   protected String getContent( TopicExpression topicExpr )
   throws TopicExpressionException
   {
      if ( !( topicExpr.getContent(  ) instanceof String ) )
      {
         throw new TopicExpressionException( "This evaluator requires the TopicExpression content to be a String." );
      }

      String expr = (String) topicExpr.getContent(  );
      if ( StringUtils.isEmpty( expr ) || !StringUtils.containsNone( expr, " \t\n\r\f" ) )
      {
         throw new InvalidTopicExpressionException( "Topic expression contains whitespace." );
      }

      return expr;
   }

   /**
    * DOCUMENT_ME
    *
    * @param topicExpr DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws TopicExpressionException DOCUMENT_ME
    */
   protected NamespaceContext getNamespaceContext( TopicExpression topicExpr )
   throws TopicExpressionException
   {
      if ( !( topicExpr.getNamespaceContext(  ) instanceof NamespaceContext ) )
      {
         throw new TopicExpressionException( "This evaluator requires the TopicExpression namespaceContext to be a NamespaceContext." );
      }

      return (NamespaceContext) topicExpr.getNamespaceContext(  );
   }

   /**
    * DOCUMENT_ME
    *
    * @param topicSpaceSet DOCUMENT_ME
    * @param topicPath DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws TopicExpressionResolutionException DOCUMENT_ME
    */
   protected TopicSpace getTopicSpace( TopicSpaceSet topicSpaceSet,
                                       QName         topicPath )
   throws TopicExpressionResolutionException
   {
      TopicSpace topicSpace = topicSpaceSet.getTopicSpace( topicPath.getNamespaceURI(  ) );
      if ( topicSpace == null )
      {
         throw new TopicExpressionResolutionException( "Topic path '" + topicPath.getPrefix(  ) + ":"
                                                       + topicPath.getLocalPart(  )
                                                       + "' references an unknown TopicSpace with namespace URI '"
                                                       + topicPath.getNamespaceURI(  ) + "'." );
      }

      return topicSpace;
   }

   /**
    * DOCUMENT_ME
    *
    * @param topicPath DOCUMENT_ME
    * @param nsContext DOCUMENT_ME
    *
    * @return DOCUMENT_ME
    *
    * @throws InvalidTopicExpressionException DOCUMENT_ME
    */
   protected QName toQName( String           topicPath,
                            NamespaceContext nsContext )
   throws InvalidTopicExpressionException
   {
      String prefix;
      String localPart;
      int    i = topicPath.indexOf( ':' );
      if ( i == -1 ) // no prefix
      {
         prefix       = "";
         localPart    = topicPath;
      }
      else if ( i == 0 )
      {
         throw new InvalidTopicExpressionException( "Topic path '" + topicPath + "' starts with a colon." );
      }
      else if ( i == ( topicPath.length(  ) - 1 ) )
      {
         throw new InvalidTopicExpressionException( "Topic path '" + topicPath + "' ends with a colon." );
      }
      else
      {
         prefix       = topicPath.substring( 0, i );
         localPart    = topicPath.substring( i + 1 );
         if ( localPart.indexOf( ':' ) != -1 )
         {
            throw new InvalidTopicExpressionException( "Local part of topic path '" + topicPath
                                                       + "' contains a colon." );
         }
      }

      String nsURI = nsContext.getNamespaceURI( prefix );
      return new QName( nsURI, localPart, prefix );
   }
}